package com.majun.service.impl;

import com.majun.dao.OrderDao;
import com.majun.dao.UserDao;
import com.majun.entity.Order;
import com.majun.entity.User;
import com.majun.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * @author majun
 * @date 2025/04/16
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    @SuppressWarnings("ALL")
    private OrderDao orderDao;

    @Autowired
    @SuppressWarnings("ALL")
    private UserDao userDao;

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void testPropagationOfRequired() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequired,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfRequired");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");

        //抛出测试
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");

        //不抛出测试
//        try {
//            throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
//        } catch (RuntimeException e) {
//            e.printStackTrace();
//        }

    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    public void testPropagationOfSupports() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfSupports,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfSupports");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");

        // 可预计的是，因为UserService上事务的传播机制是SUPPORTS，所以都没有事务，此处抛出异常，都不会回滚
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
    }

    @Override
    @Transactional(propagation = Propagation.MANDATORY,rollbackFor = Exception.class)
    public void testPropagationOfMandatory() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfMandatory,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfMandatory");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");

        // 可预计的是，因为UserService上事务的传播机制是MANDATORY，且没有创建事务；可预计的是，代码都走不到此处
        // 在进入该方法体时，就直接报错了
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void testPropagationOfRequiresNew() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequiresNew,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfMandatory");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");


        // 这里手动抛出的异常，会传递给userService
        // 1⃣️ 如果userService没有捕获该异常，会导致user和order的数据都回滚
        // 2⃣️ 如果userService捕获了异常，则只会order的数据回滚，user的数据不会回滚
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void testPropagationOfRequiresNew2() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequired,txname=" + txName);

        // try块包含所有代码时，order表中的数据不会回滚，但是user表中的数据不会回滚
        // 可以理解，即spring通过代理执行该方法时，由于内部进行了try catch，导致代理对象执行该方法时，即使
        // 内部出现异常，代理对象也捕获不到异常，也自然不会去执行回滚操作了
        try {
            Order order = new Order();
            order.setNum("testPropagationOfMandatory");
            orderDao.insertSelective(order);
            System.err.println("====OrderService插入成功====");
            throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void testPropagationOfRequiresNew3() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequiresNew,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfMandatory");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED,rollbackFor = Exception.class)
    public void testPropagationOfNotSupport() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfNotSupport,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfNotSupport");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");

        // NOT_SUPPORTED不开启事务，所以本方法中order中插入的数据不会回滚
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
    }

    @Override
    @Transactional(propagation = Propagation.NEVER,rollbackFor = Exception.class)
    public void testPropagationOfNever() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfNever,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfNever");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");

        // NEVER不开启事务，所以本方法中order中插入的数据不会回滚
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
    }

    @Override
    @Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
    public void testPropagationOfNested() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfNested,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfNested");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");

        // NESTED一定创建事务，所以本方法中order中插入的数据会回滚；
        // 且userService无法知道这个方法的执行情况
        throw new RuntimeException("OrderService手动抛出异常，观察User和Order表的数据是否都是没有插入成功的！！");
    }

    @Override
    @Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
    public void testPropagationOfNested2() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfNested,txname=" + txName);

        Order order = new Order();
        order.setNum("testPropagationOfNested");
        orderDao.insertSelective(order);
        System.err.println("====OrderService插入成功====");
    }


    @Override
    //@Transactional(isolation = Isolation.READ_UNCOMMITTED,rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    //@Transactional(isolation = Isolation.READ_COMMITTED,rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    //@Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    @Transactional(isolation = Isolation.SERIALIZABLE,rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public void testDirtyRead(User user) {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testDirtyRead,txname=" + txName);

        // 脏读
        // 脏读：本事务读到了其他事务中未提交的数据，并使用了该数据
        User dirtyUser = userDao.selectByPrimaryKey(user.getId());
        System.err.println("读取其他事务没有提交的数据:"+dirtyUser.toString());

        System.err.println("====利用读取的数据进行其他操作====");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED)
    public void testLostEdit(User user) {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequired,txname=" + txName);

        User temp = userDao.selectByPrimaryKey(user.getId());
        temp.setName("orderService");
        userDao.updateByPrimaryKey(temp);
        System.err.println("====OrderService修改数据成功:orderService====");

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED)
    //@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
    //@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.REPEATABLE_READ)
    //@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
    public void testNotRepeatableRead(User user) {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequired,txname=" + txName);

        User temp = userDao.selectByPrimaryKey(user.getId());
        temp.setName("orderService");
        userDao.updateByPrimaryKey(temp);
        System.err.println("====OrderService修改数据成功:===="+temp.toString());
    }

    @Override
    //@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED)
    //@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.REPEATABLE_READ)
    //@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
    public void testPhantomRead() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.err.println("OrderService.testPropagationOfRequired,txname=" + txName);

        User user = new User();
        user.setName("testPhantomRead");
        userDao.insertSelective(user);
        System.err.println("===testPhantomRead插入成功===");
    }
}
